package com.ghp.admin.controller;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ghp.admin.annotation.AuthCheck;
import com.ghp.admin.service.InterfaceInfoService;
import com.ghp.admin.service.UserInterfaceInfoService;
import com.ghp.common.constants.ErrorMessageConstants;
import com.ghp.common.model.dto.DeleteIdDTO;
import com.ghp.common.model.dto.QueryIdDTO;
import com.ghp.common.model.dto.UpdateIdDTO;
import com.ghp.common.model.dto.interfaceinfo.InterfaceInfoAddDTO;
import com.ghp.common.model.dto.interfaceinfo.InterfaceInfoInvokeDTO;
import com.ghp.common.model.dto.interfaceinfo.InterfaceInfoQueryDTO;
import com.ghp.common.model.dto.interfaceinfo.InterfaceInfoUpdateDTO;
import com.ghp.common.model.entity.InterfaceInfo;
import com.ghp.common.model.entity.UserInterfaceInfo;
import com.ghp.common.model.vo.InterfaceInfoVO;
import com.ghp.common.utils.BeanConvertorUtils;
import com.ghp.common.utils.ThrowUtils;
import com.ghp.common.utils.response.ResponseResult;
import com.ghp.request.annotation.RequestLimit;
import com.ghp.request.enums.RequestLimitStrategy;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.ghp.common.constants.UserConstants.ROLE_ADMIN;

/**
 * @author ghp
 * @title
 * @description
 */
@Api
@RestController
@RequestMapping("/interfaceInfo")
@Slf4j
@Validated
public class InterfaceInfoController {

    @Resource
    private InterfaceInfoService interfaceInfoService;

    @Resource
    private UserInterfaceInfoService userInterfaceInfoService;


    // region 增删改查


    @PostMapping("/add")
    @ApiOperation(value = "新增接口")
    @AuthCheck(mustRole = ROLE_ADMIN)
    public ResponseResult addInterfaceInfo(@Valid @RequestBody InterfaceInfoAddDTO interfaceInfoAddDTO) {
        return interfaceInfoService.addInterfaceInfo(interfaceInfoAddDTO);
    }

    @PostMapping("/delete")
    @ApiOperation(value = "删除接口")
    @AuthCheck(mustRole = ROLE_ADMIN)
    public ResponseResult deleteInterfaceInfo(@Valid @RequestBody DeleteIdDTO deleteIdDTO) {
        return interfaceInfoService.deleteInterfaceInfo(deleteIdDTO);
    }

    @PostMapping("/update")
    @ApiOperation(value = "更新接口")
    @AuthCheck(mustRole = ROLE_ADMIN)
    public ResponseResult updateInterfaceInfo(@Valid @RequestBody InterfaceInfoUpdateDTO interfaceInfoUpdateDTO) {
        return interfaceInfoService.updateInterfaceInfo(interfaceInfoUpdateDTO);
    }

    @PostMapping("/get/vo")
    @ApiOperation(value = "查询脱敏接口信息")
    public ResponseResult<InterfaceInfoVO> getInterfaceInfoVOById(@Valid @RequestBody QueryIdDTO queryIdDTO) {
        return interfaceInfoService.getInterfaceInfoVOById(queryIdDTO);
    }

    @PostMapping("/list/page/vo")
    @ApiOperation(value = "分页查询脱敏接口信息")
    public ResponseResult<Page<InterfaceInfoVO>> listInterfaceInfoVOByPage(@Valid @RequestBody InterfaceInfoQueryDTO interfaceInfoQueryDTO) {
        return interfaceInfoService.listInterfaceInfoVOByPage(interfaceInfoQueryDTO);
    }

    @PostMapping("/my/list/page/vo")
    @ApiOperation(value = "分页查询自身脱敏接口信息")
    public ResponseResult<Page<InterfaceInfoVO>> listInterfaceInfoVOByUserIdPage(@Valid @RequestBody InterfaceInfoQueryDTO interfaceInfoQueryDTO) {
        return interfaceInfoService.listInterfaceInfoVOByUserIdPage(interfaceInfoQueryDTO);
    }

    // endregion


    // region 发布下线接口调用

    @PostMapping("/online")
    @ApiOperation(value = "发布接口")
    @AuthCheck(mustRole = ROLE_ADMIN)
    public ResponseResult onlineInterfaceInfo(@Valid @RequestBody InterfaceInfoInvokeDTO interfaceInfoInvokeDTO) {
        return interfaceInfoService.onlineInterfaceInfo(interfaceInfoInvokeDTO);
    }

    @PostMapping("/offline")
    @ApiOperation(value = "下线接口")
    @AuthCheck(mustRole = ROLE_ADMIN)
    public ResponseResult offlineInterfaceInfo(@RequestBody UpdateIdDTO updateIdDTO) {
        return interfaceInfoService.offlineInterfaceInfo(updateIdDTO);
    }

    @PostMapping(value = "/invoke")
    @ApiOperation(value = "调用接口")
    @RequestLimit(strategy = RequestLimitStrategy.TOKEN_BUCKET, qps = 200)
    public ResponseResult<String> invokeInterfaceInfo(@RequestBody InterfaceInfoInvokeDTO interfaceInfoInvokeDTO) {
        return interfaceInfoService.invokeInterfaceInfo(interfaceInfoInvokeDTO);
    }

    @PostMapping("/buy")
    @ApiOperation(value = "开通接口")
    public ResponseResult buyInterfaceInfo(@Valid @RequestBody UpdateIdDTO updateIdDTO) {
        return interfaceInfoService.buyInterfaceInfo(updateIdDTO);
    }

    // endregion

    @GetMapping("/top")
    @ApiOperation(value = "接口分析")
    @AuthCheck(mustRole = ROLE_ADMIN)
    public ResponseResult<List<InterfaceInfoVO>> listTopInvokeInterfaceInfo() {
        // 查询调用次数前5名的接口
        List<UserInterfaceInfo> userInterfaceInfoList = userInterfaceInfoService.listTopInvokeInterfaceInfo(5);
        ThrowUtils.throwIf(Objects.isNull(userInterfaceInfoList), ErrorMessageConstants.INTERFACE_NOT_EXISTS);
        // 根据接口id分组
        Map<Long, List<UserInterfaceInfo>> interfaceInfoIdObjMap = userInterfaceInfoList.stream()
                .collect(Collectors.groupingBy(UserInterfaceInfo::getInterfaceInfoId));
        // 查询所有接口id的接口信息
        List<InterfaceInfo> list = interfaceInfoService.lambdaQuery()
                .in(InterfaceInfo::getId, interfaceInfoIdObjMap.keySet())
                .list();
        ThrowUtils.throwIf(list.isEmpty(), ErrorMessageConstants.INTERFACE_NOT_EXISTS);
        // 组装返回结果
        List<InterfaceInfoVO> result = list.stream().map(interfaceInfo -> {
            InterfaceInfoVO interfaceInfoVO = BeanConvertorUtils.copyBean(interfaceInfo, InterfaceInfoVO.class);
            interfaceInfoVO.setTotalNum(interfaceInfoIdObjMap.get(interfaceInfo.getId()).get(0).getTotalNum());
            return interfaceInfoVO;
        }).collect(Collectors.toList());
        return ResponseResult.success(result);
    }

}
